
/*********************************************
This file is part of HIM.

HIM is a module of BCI++ framowork for the implementation of Brain Computer Interface systems.
HIM is intended for use with BCI++ only.

BCI++ is a project of the Sensibilab of Politecnico Di Milano

HIM is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as 
published by the Free Software Foundation, either version 3 of 
the License, or (at your option) any later version.

HIM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU General Public License
and the GNU Lesser General Public License along with HIM.  
If not, see <http://www.gnu.org/licenses/>.
*************************************************************/

/*!
\file	Algorithm.h

  \author	Luca Maggi luca.maggi@polimi.it
  
	\date	2008-02-09 creation \n
	2008-10-07 last modification
	
	  \b Org: 
	  SENSIBILAB - Politecnico di Milano
	  
	\b COPYRIGHT: 
	LGPL
		
	\class	Algorithm Algorithm.h
		  
	\brief	
	This class manages all operation related to the processing. Processing classed should be Inherited fro this class
*/


#pragma once


#include "BaseAlgoConfig.h"
#include "BCIMatrix.h"
#include "BCIMessage.h"
#include "c4mDatatype.h"
#include "BCIStructs.h"
#include "FeedsBase.h"


#define RIGHT		8
#define LEFT		1
#define UP			16
#define DOWN		32
#define NONE_LEFT	2
#define NONE_RIGHT	4
#define NONE_TASK	5
#define NONE_IDLE	6
#define NONE		4


class Algorithm
{
public:
	/*! \fn 	Algorithm(void)
	Constructor of the object
	*/
	Algorithm(void);
	
	/*! \fn void Close(void)
	Closes the session
	*/
	void Close(void);
	/*! \fn virtual void PutSample(SampleStruct *pData);
	This function is called any time a new sample arrives: the new samples are put in the elaboration buffer and the processing 
	is activated when the length reaches MLen of SLen. You can override this function if you need any kind of sample by
	sample operation (e.g. Spatial filtering of time domain filtering
	\params pData Pointer to the new sample
	*/
	virtual void PutSample(SampleStruct *pData);
	
	virtual ~Algorithm(void);

	/*! \fn void Restart(void);
	This function is called every time the HIM receives a RESET_ALGORITHM message, and reinitialize the processing windows
	*/
	void	Restart(void);
	/*! \fn void SendConfiguration(void);
	This function can be overriden to Send any configuration parameters to the AEnima module.
	*/
	virtual void	SendConfiguration(void);


	/*!\fn int	GetLastClassification(int Class);
	For internal use: 
	\return the last classification
	*/
	int	GetLastClassification(void);
	/*!\fn void	ToggleShow(void)
	For internal use: toggle the show of the feedback plot
	\return New show status
	*/
	void	ToggleShow(void);
	
	/*!\fn Algostats GetAlgorithmStatistics(void)
	For internal use
	\returns a struct \struct Alogostat containing some debugging statistics
	*/
	Algostats GetAlgorithmStatistics(void);

	/*! Writes data to the socket channel
	/param pData Pointer to the data to send
	/param Len size in bytes of the data pointed by /a pdata
	*/
	void	WriteOut(char *pData,int Len);


	//!Pointer to the storage space for the main window
	float			*MainWindow;
	//!Pointer to the storage space for the secondary window
	float			*SecWindow;
	//!Storage space for feedbacks
	float			FeedBack[MAX_FEEDS];
	//!Number of feedback currently being generated
	int				FeedLen;
	//!Length of the main window
	int				MainWinLen;
	//!Length of the secondary window
	int				SecWinLen;
	//!Data cursor for the main window
	int				MainCursor;
	//!Data cursor for the secondary window
	int				SecCursor;
	//!Value of the last classification
	int				LastClassification;
	
	//! Descriptor for the main window
	BCIMatrix		*c4mMainWindow;

	//! Descriptor for the secondary window
	BCIMatrix		*c4mSecWindow;
	
	//!If this variable is false the communication of the feedback to AEnima using the /fn SetFeedback function is disabled
	bool			EnableFeedback;
	//!If this variable is false the communication of the feedback to AEnima using the /fn SetClassification function is disabled
	bool			EnableClassification;
	
	/*! fn virtual void RunBeforeStart(void)
	This virtual function is execute before starting the signal acquisition
	*/	
	virtual void RunBeforeStart(void){
	};

	/*! fn virtual void RunAfterStop(void)
	This virtual function is execute after stopping the signal acquisition
	*/	
	virtual void RunAfterStop(void){ 
	};
	
	/*! fn virtual void RunBeforeStop(void)
	This virtual function is execute after stopping the signal acquisition
	*/	
	virtual void RunBeforeStop(void){
	};

	virtual void SendValue(bool *flag, int sizeFlag, int *value, int sizeValue)
	{	};

		//!Internal variables for algorithm profiling
	TimerParams		MainTimer,ShortTimer;
	
	bool Error;
	bool SingleSample;
	int MatError;
	//! For internal use only
	int GetData(char *pBuffer);
	FeedsBase	*pOutputWindow;

private:
	int		SocketLen;
	char	SocketBuffer[2048];
	void	StopSecTimeCounter(void);
	void	StartSecTimeCounter(void);
	void	StopMainTimeCounter(void);
	void	StartMainTimeCounter(void);
	void	StartCounter(TimerParams *pParams);
	void	StopCounter(TimerParams *pParams);

	
	Algostats		AlgoPerf;

protected:
	/*! \fn void	ShiftMainWin(int Len);
	This function shifts the main windows of the amount of samples indicated by \a Len
	*/
	void	ShiftMainWin(int Len);
	/*! \fn void	ShiftMainWin(int Len);
	This function shifts the secondary window of the amount of samples indicated by \a Len
	*/
	void	ShiftSecondaryWin(int Len);
	virtual void	Init(void){};
	
	/*! fn virtual void	RunMainWin(void);
	Virtual function: you should implement it if you have a Main window length bigger than zero.
	In this function you should put you signal processing and at the end of this you can call SetFeedback and SetClassification to
	set the result of your processing. Please call ShiftMainWindow after the processing.
	*/
	virtual void	RunMainWin(void);
	/*! fn virtual void	RunSecondaryWin(void);
	Virtual function: you should implement it if you have a Main window length bigger than zero.
	In this function you should put you signal processing and at the end of this you can call SetFeedback and SetClassification to
	set the result of your processing. Please call ShiftSecondaryWindow after the processing.
	*/	
	virtual void	RunSecWin(void);

	/*! fn virtual void	RunSingleSample(void);
	Virtual function: you can use this function to elaborate any single sample.
	*/	
	virtual void	RunSingleSample(void);
	/*! \fn 	void Open(int MLen,int SLen,int NumerOfValidDataChannels,int Feedback,int FeedbackGUI)
	Initializes the object on the basis of your needs
	/a MLen Length (in samples) of the main elaboration window
	/a SLen Length (in samples) of the secondary elaboration window
	/a NumerOfValidDataChannels Number of signal channel used from the instrument
	/a Feedback Number of feedback values that must be sent to the UI
	/a FeedbackGUI kind of feedback gui
	*/
	void Open(int MLen,int SLen,int NumerOfValidDataChannels,int Feedback,int FeedbackGUI = 0,int AlgorithmFrequency= 4);

	/*!\fn void	SetClassification(int Class);
	This function set the classification value to be sent to the AEnima Module
	*/
	void	SetClassification(int Class);
	/*!\fn void	SetFeedback(float *pFeedback);
	This function set the feedback values to be sent to the AEnima Module
	*/
	void	SetFeedback(float *pFeedback);

	
	int						ChNumber;
	int						SampleFreq;
};


